#include "hal.h"
#include "gd32f1x0.h"

static uint32_t s_SysTick_Cnt=0;


static uint32_t s_HalSwTab[][2]={
	{HAL_SW0_PORT,HAL_SW0_PIN},
	{HAL_SW1_PORT,HAL_SW1_PIN},
	{HAL_SW2_PORT,HAL_SW2_PIN},
	{HAL_SW3_PORT,HAL_SW3_PIN},
	{HAL_SW4_PORT,HAL_SW4_PIN},
	{HAL_SW5_PORT,HAL_SW5_PIN},
	{HAL_SW6_PORT,HAL_SW6_PIN},
	{HAL_SW7_PORT,HAL_SW7_PIN},
	{HAL_SW8_PORT,HAL_SW8_PIN},
	{HAL_SW9_PORT,HAL_SW9_PIN},
	{HAL_SW10_PORT,HAL_SW10_PIN},
	{HAL_SW11_PORT,HAL_SW11_PIN},
	{HAL_SW12_PORT,HAL_SW12_PIN},
	{HAL_SW13_PORT,HAL_SW13_PIN},
	{HAL_SW14_PORT,HAL_SW14_PIN},
	{HAL_SW15_PORT,HAL_SW15_PIN},
	{HAL_SW16_PORT,HAL_SW16_PIN},
	{HAL_SW17_PORT,HAL_SW17_PIN},
	{HAL_SW18_PORT,HAL_SW18_PIN},
	{HAL_SW19_PORT,HAL_SW19_PIN},
	{HAL_SW20_PORT,HAL_SW20_PIN},
	{HAL_SW21_PORT,HAL_SW21_PIN},
	{HAL_SW22_PORT,HAL_SW22_PIN},
	{HAL_SW23_PORT,HAL_SW23_PIN},
};


static uint32_t s_HalLedTab[][2]={
	{HAL_LED0_PORT,HAL_LED0_PIN},
	{HAL_LED1_PORT,HAL_LED1_PIN},
	{HAL_LED2_PORT,HAL_LED2_PIN},
	{HAL_LED3_PORT,HAL_LED3_PIN},
	{HAL_LED4_PORT,HAL_LED4_PIN},
	{HAL_LED5_PORT,HAL_LED5_PIN},
	{HAL_LED6_PORT,HAL_LED6_PIN},
	{HAL_LED7_PORT,HAL_LED7_PIN},
	{HAL_LED8_PORT,HAL_LED8_PIN},
	{HAL_LED9_PORT,HAL_LED9_PIN},
	{HAL_LED10_PORT,HAL_LED10_PIN},
	{HAL_LED11_PORT,HAL_LED11_PIN},
	{HAL_LED12_PORT,HAL_LED12_PIN},
	{HAL_LED13_PORT,HAL_LED13_PIN},
	{HAL_LED14_PORT,HAL_LED14_PIN},
	{HAL_LED15_PORT,HAL_LED15_PIN},
	{HAL_LED16_PORT,HAL_LED16_PIN},
	{HAL_LED17_PORT,HAL_LED17_PIN},
	{HAL_LED18_PORT,HAL_LED18_PIN},
	{HAL_LED19_PORT,HAL_LED19_PIN},
	{HAL_LED20_PORT,HAL_LED20_PIN},
	{HAL_LED21_PORT,HAL_LED21_PIN},
	{HAL_LED22_PORT,HAL_LED22_PIN},
	{HAL_LED23_PORT,HAL_LED23_PIN},
};


void SysTick_Handler(void)
{
    s_SysTick_Cnt++;
}



static void _Hal_Key_Init(void){
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_GPIOF);
	uint8_t i;
	for(i=0;i<24;i++){
	
    	gpio_mode_set(s_HalSwTab[i][0], GPIO_MODE_INPUT, GPIO_PUPD_NONE,s_HalSwTab[i][1]);
   
	}

}


static void _Hal_Led_Init(void){

	uint8_t i;
	for(i=0;i<24;i++){
	
    	gpio_mode_set(s_HalLedTab[i][0], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,s_HalLedTab[i][1]);
   
	}
}

static void _Hal_Uart_Init(void){
	rcu_periph_clock_enable(RCU_USART0);
	gpio_mode_set(HAL_485_STA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE,HAL_485_STA_PIN);

	usart_baudrate_set(HAL_USART_PORT,HAL_USART_BAUDRATE);

	usart_parity_config(HAL_USART_PORT,USART_PM_NONE);

	usart_word_length_set(HAL_USART_PORT,USART_WL_8BIT);
	
	usart_stop_bit_set(HAL_USART_PORT,USART_STB_1BIT);

	usart_transmit_config(HAL_USART_PORT,USART_TRANSMIT_ENABLE);

	usart_receive_config(HAL_USART_PORT,USART_RECEIVE_ENABLE);

	usart_clock_enable(HAL_USART_PORT);

	usart_interrupt_enable(HAL_USART_PORT,USART_INT_RBNE);
}


static void _Hal_SysTick_Init(void){
	 /* setup systick timer for 1000Hz interrupts */
    if (SysTick_Config(SystemCoreClock / 1000)){
      
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00);
}

static void _Hal_iwdog_init(void){
	rcu_periph_clock_enable(RCU_WWDGT);
	fwdgt_config(FWDGT_PSC_DIV4,0xfff);
	fwdgt_write_enable();
	fwdgt_enable();
}


void Hal_Init(void){
	_Hal_SysTick_Init();
	_Hal_Key_Init();
	_Hal_Led_Init();
	_Hal_Uart_Init();
}



uint32_t Hal_SysTick_Get(void){
	return s_SysTick_Cnt;
}


void USART0_IRQHandler(void){
	uint16_t data=0;
	if(usart_interrupt_flag_get(HAL_USART_PORT,USART_INT_FLAG_RBNE)!=RESET){
		data=usart_data_receive(HAL_USART_PORT);
	}

	usart_interrupt_flag_clear(HAL_USART_PORT,USART_INT_FLAG_EB|USART_INT_FLAG_RT|USART_INT_FLAG_AM|
								USART_INT_FLAG_PERR|USART_INT_FLAG_TBE|USART_INT_FLAG_TC|USART_INT_FLAG_RBNE|
								USART_INT_FLAG_RBNE_ORERR|USART_INT_FLAG_IDLE|USART_INT_FLAG_LBD|USART_INT_FLAG_WU|
								USART_INT_FLAG_CTS|USART_INT_FLAG_ERR_NERR|USART_INT_FLAG_ERR_ORERR|USART_INT_FLAG_ERR_FERR);

}

void USART1_IRQHandler(void){

	usart_interrupt_flag_clear(HAL_USART_PORT,USART_INT_FLAG_EB|USART_INT_FLAG_RT|USART_INT_FLAG_AM|
								USART_INT_FLAG_PERR|USART_INT_FLAG_TBE|USART_INT_FLAG_TC|USART_INT_FLAG_RBNE|
								USART_INT_FLAG_RBNE_ORERR|USART_INT_FLAG_IDLE|USART_INT_FLAG_LBD|USART_INT_FLAG_WU|
								USART_INT_FLAG_CTS|USART_INT_FLAG_ERR_NERR|USART_INT_FLAG_ERR_ORERR|USART_INT_FLAG_ERR_FERR);
}

void Hal_Uart_Send(uint8_t* pBuffer,uint32_t pLen)
{
	uint32_t i;
	for(i=0;i<pLen;i++){
		usart_data_transmit(HAL_USART_PORT,pBuffer[i]);
		while(usart_interrupt_flag_get(HAL_USART_PORT,USART_INT_FLAG_TC)!=RESET);
		usart_interrupt_flag_clear(HAL_USART_PORT,USART_INT_FLAG_TC);
	}
}


void Hal_Uart_SendByte(uint8_t pData){
	usart_data_transmit(HAL_USART_PORT,pData);
	while(usart_interrupt_flag_get(HAL_USART_PORT,USART_INT_FLAG_TC)!=RESET);
	usart_interrupt_flag_clear(HAL_USART_PORT,USART_INT_FLAG_TC);
}

void Hal_Iwdgt_feed(void){
	fwdgt_counter_reload();
}


uint8_t Hal_Flash_Ereae(uint32_t Address){
	fmc_unlock();
	
	fmc_flag_clear(FMC_FLAG_END);
	fmc_flag_clear(FMC_FLAG_PGERR);
	fmc_flag_clear(FMC_FLAG_WPERR);
	fmc_flag_clear(FMC_FLAG_BUSY);
	fmc_page_erase(Address);
	fmc_lock();
	return 0;
}

uint8_t Hal_Flash_Write(uint8_t* pBuffer,uint32_t Address,uint32_t pLen){
	uint32_t tWriteStartAddr;
	uint8_t tRetSta=0;
	fmc_unlock();
	fmc_flag_clear(FMC_FLAG_END);
	fmc_flag_clear(FMC_FLAG_PGERR);
	fmc_flag_clear(FMC_FLAG_WPERR);
	fmc_flag_clear(FMC_FLAG_BUSY);
	tWriteStartAddr=Address;
	while(tWriteStartAddr<(Address+pLen)){
		
		fmc_word_program(Address+tWriteStartAddr,(*(uint32_t*)(uint32_t)(pBuffer+tWriteStartAddr)));

		fmc_flag_clear(FMC_FLAG_END);
		fmc_flag_clear(FMC_FLAG_PGERR);
		fmc_flag_clear(FMC_FLAG_WPERR);
		fmc_flag_clear(FMC_FLAG_BUSY);

		if((*(uint32_t*)(pBuffer+tWriteStartAddr))!=(*(uint32_t*)(Address+tWriteStartAddr))){
			if(tRetSta<0xff){
				tRetSta+=1;
			}
		}
		tWriteStartAddr+=4;	
	}

	fmc_lock();

	return tRetSta;
}

uint8_t Hal_Flash_Read(uint8_t* pBuffer,uint32_t Address,uint32_t PLen){
	uint32_t pReadAddr;
	pReadAddr=Address;
	while(pReadAddr<(Address+PLen)){
		(*(uint8_t*)(pBuffer+pReadAddr))=(*(uint8_t*)(uint32_t)(Address+pReadAddr));
		pReadAddr+=1;
	}
	return 0;
}


uint8_t Hal_KeyInput_Read(uint8_t KeyId){
	int ret;
	ret=gpio_input_bit_get(s_HalSwTab[KeyId][0],s_HalSwTab[KeyId][1]);
	if(ret==SET){
		return 1;
	}
	return 0;
}


void Hal_LedOutput_Write(uint8_t LedId,uint8_t Value){
	if(Value>0){
		gpio_bit_write(s_HalLedTab[LedId][0],s_HalLedTab[LedId][1],SET);
	}else{
		gpio_bit_write(s_HalLedTab[LedId][0],s_HalLedTab[LedId][1],SET);
	}
}



